﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PerCederberg.Grammatica.Runtime;

namespace SafeScript.MetaModel.Statements
{
    /// <summary>
    /// Definition of a local variable.
    /// </summary>
    public class VarStatement : Statement, INamed
    {
        public string Name { get; set; }
        public ITypeDef Type;
        public Operator InitialValue;
        /// <summary>
        /// May be null. The getter, setter, MemberFunction or FunctionOperator in which this
        /// local variable has been defined.
        /// </summary>
        public object Owner;

        public override void ComputeType(ErrorReport report)
        {
            // Infere type?
            if (this.InitialValue != null && this.Type == null)
            {
                ITypeDef t = this.InitialValue.ComputeType(null, false, report);
                if (t == null)
                    return;
                InstanceType it = this.ToInstance(ref this.InitialValue, t, report);
                // Some error?
                if (it == null)
                    return;
                this.Type = it;
            }
            // No type specified at all?
            else if (this.InitialValue == null && this.Type == null)
            {
                report.Add(new ErrorEntry(this.Node) { Type = ErrorType.UnresolvedType, Info = this.Name });
            }
            // Type and initialization specified?
            else if (this.InitialValue != null)
            {
                ITypeDef t = this.InitialValue.ComputeType(this.Type, false, report);
                // Some error?
                if (t == null)
                    return;
                InstanceType it = this.ToInstance(ref this.InitialValue, t, report);
                // Some error?
                if (it == null)
                    return;
                //if (!it.CanBeAssignedTo(this.Type))
                if ( this.ConvertTo(ref this.InitialValue, t, this.Type, report ) == null )
                    return;
            }
        }

        public bool IsInInterator
        {
            get
            {
                if ((this.Owner is MemberFunction && (this.Owner as MemberFunction).IsIterator) ||
                    (this.Owner is FunctionOperator && (this.Owner as FunctionOperator).IsIterator))
                    return true;
                return false;
            }
        }
    }
}
